package com.siao.component.scroller
{
	import com.greensock.TweenMax;
	import com.greensock.easing.Strong;
	import com.siao.display.Align;
	import com.siao.display.Margin;
	
	import flash.display.DisplayObject;
	import flash.events.Event;
	import flash.events.MouseEvent;
	
	/**
	 * 滚动面板
	 * @author SiaoLeon
	 */
	public class ScrollPanel extends ScrollRect
	{
		// -------------------------------------------------------------------------------------------------------- 静态常量
		
		// -------------------------------------------------------------------------------------------------------- 静态变量
		
		// -------------------------------------------------------------------------------------------------------- 静态方法
		
		// -------------------------------------------------------------------------------------------------------- 静态函数
		
		// -------------------------------------------------------------------------------------------------------- 属性
		
		private var _scrollWheel:Boolean;
		
		/**
		 * 是否开启鼠标滚轮垂直滚动
		 * @return
		 */
		public function get scrollWheel():Boolean
		{
			return this._scrollWheel;
		}
		
		public function set scrollWheel(value:Boolean):void
		{
			this._scrollWheel = value;
			
			this.registerEventListeners();
		}
		
		private var _vScrollPolicy:String = ScrollPolicy.AUTO;
		
		/**
		 * 垂直滚动条策略，参考ScrollPolicy的值
		 * @return
		 */
		public function get vScrollPolicy():String
		{
			return this._vScrollPolicy;
		}
		
		public function set vScrollPolicy(value:String):void
		{
			this._vScrollPolicy = value;
			
			this.resize();
		}
		
		private var _hScrollPolicy:String = ScrollPolicy.AUTO;
		
		/**
		 * 水平滚动条策略，参考ScrollPolicy的值
		 * @return
		 */
		public function get hScrollPolicy():String
		{
			return this._hScrollPolicy;
		}
		
		public function set hScrollPolicy(value:String):void
		{
			this._hScrollPolicy = value;
			
			this.resize();
		}
		
		private var _scrollSize:Number;
		
		/**
		 * 行/列尺寸，该数值将影响向前、向后滚动的间隔尺寸
		 * @return
		 */
		public function get scrollSize():Number
		{
			return this._scrollSize;
		}
		
		public function set scrollSize(value:Number):void
		{
			this._scrollSize = value;
			
			this.initScrollBar();
		}
		
		private var _vScrollBar:ScrollBar;
		
		/**
		 * 垂直滚动条
		 * @return
		 */
		public function get vScrollBar():ScrollBar
		{
			return (this._vScrollBar == null) ? new ScrollBar() : this._vScrollBar;
		}
		
		public function set vScrollBar(value:ScrollBar):void
		{
			if (this.contains(this.vScrollBar))
			{
				this.removeChild(this.vScrollBar);
			}
			
			this.vScrollBar.removeEventListener(Event.CHANGE, onScroll);
			
			this._vScrollBar = value;
			this.vScrollBar.alignH = Align.RIGHT;
			this.addChild(this.vScrollBar);
			
			this.resize();
		}
		
		private var _hScrollBar:ScrollBar;
		
		/**
		 * 水平滚动条
		 * @return
		 */
		public function get hScrollBar():ScrollBar
		{
			return (this._hScrollBar == null) ? new ScrollBar() : this._hScrollBar;
		}
		
		public function set hScrollBar(value:ScrollBar):void
		{
			if (this.contains(this.hScrollBar))
			{
				this.removeChild(this.hScrollBar);
			}
			
			this.hScrollBar.removeEventListener(Event.CHANGE, onScroll);
			
			this._hScrollBar = value;
			this.hScrollBar.alignV = Align.BOTTOM;
			this.addChild(this.hScrollBar);
			
			this.resize();
		}
		
		// -------------------------------------------------------------------------------------------------------- 变量
		
		// -------------------------------------------------------------------------------------------------------- 构造
		
		/**
		 * 构造函数
		 */
		public function ScrollPanel(content:DisplayObject, vScrollBar:ScrollBar=null, hScrollBar:ScrollBar=null)
		{
			this._vScrollBar = vScrollBar;
			this._hScrollBar = hScrollBar;
			this.vScrollBar.alignH = Align.RIGHT;
			this.hScrollBar.alignV = Align.BOTTOM;
			this.addChild(this.vScrollBar);
			this.addChild(this.hScrollBar);
			
			super(content);
		}
		
		// -------------------------------------------------------------------------------------------------------- 方法
		
		override public final function clear():void
		{
			for (var i:int = this.numChildren - 1; i >= 0; i--)
			{
				var child:DisplayObject = this.getChildAt(i);
				
				if (child == this.container || child == this.maskLayer || child == this.vScrollBar || child == this.hScrollBar)
				{
					continue;
				}
				
				this.removeChild(child);
			}
		}
		
		override public function resize():void
		{
			super.resize();
			
			var showWidth:Number = this.width - this.paddingLeft - this.paddingRight - this._maskMargin.left - this._maskMargin.right;
			var showHeight:Number = this.height - this.paddingTop - this.paddingBottom - this._maskMargin.top - this._maskMargin.bottom;
			
			this.hScrollBar.visible = (this.height - this.paddingTop - this.paddingBottom >= this.hScrollBar.height && (this.hScrollPolicy == ScrollPolicy.ALWAYS || (this.hScrollPolicy == ScrollPolicy.AUTO && this.content.width > showWidth)));
			this.vScrollBar.visible = (this.width - this.paddingLeft - this.paddingRight >= this.vScrollBar.width && (this.vScrollPolicy == ScrollPolicy.ALWAYS || (this.vScrollPolicy == ScrollPolicy.AUTO && this.content.height > showHeight)));
			
			this.hScrollBar.visible = (this.hScrollPolicy == ScrollPolicy.AUTO && this.vScrollBar.visible) ? this.content.width > showWidth - this.vScrollBar.width : this.hScrollBar.visible;
			this.vScrollBar.visible = (this.vScrollPolicy == ScrollPolicy.AUTO && this.hScrollBar.visible) ? this.content.height > showHeight - this.hScrollBar.height : this.vScrollBar.visible;
			
			this.resizeMask();
			this.resizeContainer();
			
			this.initScrollBar();
		}
		
		override public final function moveTo(x:Number, y:Number):void
		{
			//检测单位模式定位
			x = (this.hScrollBar.unitDragMode) ? Math.round(x / this.hScrollBar.unit) * this.hScrollBar.unit : x;
			y = (this.vScrollBar.unitDragMode) ? Math.round(y / this.vScrollBar.unit) * this.vScrollBar.unit : y;
			
			if (!this.scrollEasing)
			{
				this.hScrollBar.current = this.maskMarginLeft - this.container.x;
				this.vScrollBar.current = this.maskMarginTop - this.container.y;
			}
			
			super.moveTo(x, y);
		}
		
		override public final function dragTo(x:Number, y:Number):void
		{
			//检测单位模式定位
			x = (this.hScrollBar.unitDragMode) ? Math.round(x / this.hScrollBar.unit) * this.hScrollBar.unit : x;
			y = (this.vScrollBar.unitDragMode) ? Math.round(y / this.vScrollBar.unit) * this.vScrollBar.unit : y;
			
			super.dragTo(x, y);
			
			this.hScrollBar.current = this.maskMarginLeft - this.container.x;
			this.vScrollBar.current = this.maskMarginTop - this.container.y;
		}
		
		// -------------------------------------------------------------------------------------------------------- 函数
		
		override protected final function resizeMask():void
		{
			this.maskLayer.width = Math.max(0, (this.vScrollBar.visible) ? this.width - this.paddingLeft - this.paddingRight - this._maskMargin.left - this._maskMargin.right - this.vScrollBar.width : this.width - this.paddingLeft - this.paddingRight - this._maskMargin.left - this._maskMargin.right);
			this.maskLayer.height = Math.max(0, (this.hScrollBar.visible) ? this.height - this.paddingTop - this.paddingBottom - this._maskMargin.top - this._maskMargin.bottom - this.hScrollBar.height : this.height - this.paddingTop - this.paddingBottom - this._maskMargin.top - this._maskMargin.bottom);
		}
		
		override protected final function positionContainer():void
		{
			super.positionContainer();
			
			//设定内容位置
			this.container.x = (this.hScrollBar.unitDragMode) ? Math.round(this.container.x / this.hScrollBar.unit) * this.hScrollBar.unit : this.container.x;
			this.container.y = (this.vScrollBar.unitDragMode) ? Math.round(this.container.y / this.vScrollBar.unit) * this.vScrollBar.unit : this.container.y;
			
			this.initScrollBar();
		}
		
		override protected final function registerEventListeners():void
		{
			super.registerEventListeners();
			
			if (this.scrollWheel)
			{
				this.addEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheel, false, 0, true);
			}
			else
			{
				this.removeEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheel);
			}
			
			this.hScrollBar.addEventListener(Event.CHANGE, onScroll, false, 0, true);
			this.vScrollBar.addEventListener(Event.CHANGE, onScroll, false, 0, true);
		}
		
		override protected final function removeEventListeners():void
		{
			super.removeEventListeners();
			
			this.removeEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheel);
			
			this.hScrollBar.removeEventListener(Event.CHANGE, onScroll);
			this.vScrollBar.removeEventListener(Event.CHANGE, onScroll);
		}
		
		override protected final function updatePositionH(targetX:Number):void
		{
			this.hScrollBar.current = this.maskMarginLeft - this.container.x;
			
			super.updatePositionH(targetX);
		}
		
		override protected final function updatePositionV(targetY:Number):void
		{
			this.vScrollBar.current = this.maskMarginTop - this.container.y;
			
			super.updatePositionV(targetY);
		}
		
		/**
		 * 初始化滚动条
		 */
		private function initScrollBar():void
		{
			//设定滚动条数值
			var range:Margin = this.dragRange();
			this.hScrollBar.setValue(Math.min(0, this.content.width - this.maskLayer.width), Math.max(0, this.content.width - this.maskLayer.width), isNaN(this.scrollSize) ? this.maskLayer.width / 20 : this.scrollSize, this.maskLayer.width);
			this.vScrollBar.setValue(Math.min(0, this.content.height - this.maskLayer.height), Math.max(0, this.content.height - this.maskLayer.height), isNaN(this.scrollSize) ? this.maskLayer.height / 20 : this.scrollSize, this.maskLayer.height);
			
			this.hScrollBar.width = (this.vScrollBar.visible) ? this.width - this.paddingLeft - this.paddingRight - this.vScrollBar.width : this.width - this.paddingLeft - this.paddingRight;
			this.vScrollBar.height = (this.hScrollBar.visible) ? this.height - this.paddingTop - this.paddingBottom - this.hScrollBar.height : this.height - this.paddingTop - this.paddingBottom;
			
			this.hScrollBar.current = this.maskMarginLeft - this.container.x;
			this.vScrollBar.current = this.maskMarginTop - this.container.y;
		}
		
		/**
		 * 滚动条变更时
		 * @param event
		 */
		private function onScroll(event:Event):void
		{
			//获取内容目标坐标
			var x:Number = this.maskMarginLeft - this.hScrollBar.current;
			var y:Number = this.maskMarginTop - this.vScrollBar.current;
			
			//如果与当前位置一致则返回
			if (this.container.x == x && this.container.y == y)
			{
				return;
			}
			
			//移除所有缓动效果
			TweenMax.killAll();
			
			if (this.scrollEasing)
			{
				//缓动定位
				var time:Number = Math.max(Math.abs(this.container.x - x) / this.hScrollBar.amount, Math.abs(this.container.y - y) / this.vScrollBar.amount);
				TweenMax.to(this.container, Math.min(this.maxEaseTime, Math.max(this.minEaseTime, time)), {x: x, y: y, ease: Strong.easeOut});
			}
			else
			{
				//直接定位
				this.container.x = x;
				this.container.y = y;
			}
		}
		
		/**
		 * 鼠标滚动时
		 * @param event
		 */
		private function onMouseWheel(event:MouseEvent):void
		{
			this.vScrollBar.setCurrent(this.vScrollBar.current + this.vScrollBar.amount * event.delta);
		}
	
	}
}
